package net.yslibrary.licenseadapter;

import com.jakewharton.disklrucache.DiskLruCache;
import net.yslibrary.licenseadapter.cache.Utils;
import net.yslibrary.licenseadapter.internal.ExpandableLibrary;
import net.yslibrary.licenseadapter.internal.GitHubLibrary;
import net.yslibrary.licenseadapter.internal.OnCallBack;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.animation.Animator.CurveType;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.Component.ClickedListener;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.Context;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.IntentConstants;
import ohos.utils.LruBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import ohos.utils.net.Uri;


/**
 * A which displays expandable items with a library and its license.
 * <p>
 * For optimal performance, the  using this adapter should be attached a support
 * library context such as the .
 *
 * @see Library BaseItemProvider
 * @see Licenses
 */
public class LicenseAdapter extends BaseItemProvider implements
        ExpandableLibrary.ExpandListener , Component.TouchEventListener {
    private List<ExpandableLibrary> datas;
    private static final int TYPE_LIBRARY = 0;
    private static final int TYPE_LICENSE = 1;
    private String content = "";
    private Context context;
    private int DEGREES = 180;
    private int DURATION  = 500;
    private String urlPath ="";
    private final LruBuffer<Library, License> cachedLicenses = new LruBuffer<>();
    private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
    private static final String CACHE_DIR_NAME = "license-adapter-cache";
    private static final String address = "resources/rawfile/baseurl.text";
    private static String URL_BASE1 = "";
    private DiskLruCache diskLruCache;
    private Component concomponent;
    public LicenseAdapter(Context context,  List<Library> datas) {
    this.context = context;

    List<ExpandableLibrary> wrappedLibraries = new ArrayList<>();
    for (Library library : datas) {
      wrappedLibraries.add(new ExpandableLibrary(library, this));
     }
    this.datas = Collections.unmodifiableList(wrappedLibraries);
  }

  @Override
  public int getCount() {
    return datas.size();
  }

  @Override
  public Object getItem(int index) {
    return datas.get(index);
  }

  @Override
  public long getItemId(int index) {
    return index;
  }
  public void expand(Component component, boolean isAnimator) {
    if(isAnimator) {
    AnimatorProperty animator = component.createAnimatorProperty();
    if(animator.isRunning()){
            animator.stop();
    }
    animator.setCurveType(CurveType.LINEAR);
    animator.setDuration(DURATION);
    animator.rotate(DEGREES);
    animator.start();
    }else{
        component.setRotation(DEGREES);
    }
  }

  /**
   * Collapse animation to hide the discoverable content.
   *
   * @param component
   */
  public void collapse(Component component) {
   AnimatorProperty animator = component.createAnimatorProperty();
   if(animator.isRunning()){
          animator.stop();
    }
    animator.setCurveType(CurveType.LINEAR);
    animator.setDuration(DURATION);
    animator.rotate(0);
    animator.start();
  }
  @Override
  public Component getComponent(int i, Component convertComponent, ComponentContainer componentContainer) {
    convertComponent = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_list_item,
            null, false);

    DirectionalLayout namelayout = (DirectionalLayout)convertComponent.findComponentById(ResourceTable.Id_layout_Dire);
    concomponent = namelayout;
    concomponent.setTouchEventListener(this::onTouchEvent);
    openCache();
    Text text1 = (Text) convertComponent.findComponentById(ResourceTable.Id_text1);
    Text text2 = (Text) convertComponent.findComponentById(ResourceTable.Id_text2);
    Text licenseText = (Text) convertComponent.findComponentById(ResourceTable.Id_licenseId);
    Text licenseName =  (Text)convertComponent.findComponentById(ResourceTable.Id_licenseNme);
    Image image1 = (Image) convertComponent.findComponentById(ResourceTable.Id_image1);
    DirectionalLayout layoutlicense =  (DirectionalLayout)convertComponent.findComponentById(ResourceTable.Id_layout_license);


    text1.setText( datas.get(i).getLibrary().getName());
    text2.setText(datas.get(i).getLibrary().getAuthor());
    if((i == 0 ) || (i == 1)){
          image1.setVisibility(Image.HIDE);
    }
    if(i ==(datas.size() - 1)){
          text1.setTextColor(Color.BLACK);
    }

    if(datas.get(i).isExpanded()) {
    licenseName.setText(datas.get(i).getLibrary().getLicense().getName()+"\n");
    licenseText.setText(ResourceTable.String_license_loading);
    licenseText.setText(content);
    datas.get(i).setExpanded(true);
    layoutlicense.setVisibility(Component.VISIBLE);
    expand(image1, false);
    licenseName.setClickedListener(new ClickedListener() {
                @Override
                public void onClick(Component component) {
                    String lic =datas.get(i).getLibrary().getLicense().getUrl();
                    initWeb(lic);
                }
            });
        }else{
            datas.get(i).setExpanded(false);
            licenseText.setText(datas.get(i).getLibrary().getLicense().getText());
            layoutlicense.setVisibility(Component.HIDE);
        }

    concomponent.setClickedListener(new ClickedListener() {
          @Override
          public void onClick(Component component) {
              if((i == 0 ) || (i == 1)){
              }else{
                  datas.get(i).setExpanded(!datas.get(i).isExpanded());

                  if(datas.get(i).isExpanded()){

                      load(datas.get(i).getLibrary());
                      expand(image1,true);
                      layoutlicense.setVisibility(Component.VISIBLE);
                      licenseName.setText(datas.get(i).getLibrary().getLicense().getName()+"\n");
                      licenseText.setText(ResourceTable.String_license_loading);
                      String cacheData = getCacheData(datas.get(i).getLibrary().getAuthor());
                      if(null != cacheData){
                          licenseText.setText(cacheData);
                      }else{
                          GitHubLibrary.setCompleteInter(new OnCallBack() {
                              @Override
                              public void onResultComplete(License license) {
                                  context.getUITaskDispatcher().delayDispatch(new Runnable() {
                                      @Override
                                      public void run() {

                                          if(license != null){
                                              licenseName.setText(license.getName()+"\n");
                                          }
                                          licenseName.setText(datas.get(i).getLibrary().getLicense().getName()+"\n");
                                          licenseText.setText(ResourceTable.String_license_loading);
                                          licenseText.setText(license.getText());

                                          content = license.getText();
                                          saveCacheData(datas.get(i).getLibrary().getAuthor(),license.getText());
                                          notifyDataChanged();
                                      }
                                  }, 0);
                              }
                          });
                      }
                  }else{
                      layoutlicense.setVisibility(Component.HIDE);
                      collapse(image1);
                  }
              }

           }
        });

    text1.setClickedListener(new ClickedListener() {
          @Override
          public void onClick(Component component) {
           if((i ==0 ) || (i == 1)){
              image1.setVisibility(Image.HIDE);
              urlPath = datas.get(i).getLibrary().getLicense().getUrl();
            }else if(i ==(datas.size() - 1)){
              urlPath ="";
            }else{
               URL_BASE1 =getUrl(address,context);
              urlPath = URL_BASE1+datas.get(i).getLibrary().getAuthor()+"/"+datas.get(i).getLibrary().getName();
            }
            initWeb(urlPath);
           }
         });
         return convertComponent;
      }

        @Override
        public void notifyDataChanged() {
            super.notifyDataChanged();
        }

    /*
     * 浏览器
     * */
    private void initWeb(String urlString) {
     if((null ==urlString) || "".equals(urlString)){
       return;
     }
    Intent intents = new Intent();
    Operation operation = new Intent.OperationBuilder()
            .withUri(Uri.parse(urlString))
            .withAction(IntentConstants.ACTION_SEARCH)
            .build();
    intents.setOperation(operation);
    context.startAbility(intents,1);
  }
    public void load(final Library library) {
    License cache = cachedLicenses.get(library);
    if (cache == null) {
      EXECUTOR.execute(new Runnable() {
        @Override
        public void run() {
          try {
            library.load(new File(context.getCacheDir(), CACHE_DIR_NAME + File.separator +
                    library.getAuthor() + File.separator + library.getName()));
            License license = library.getLicense();
            cachedLicenses.put(library, license);
            notify(license, null);
          } catch (Exception e) {
            notify(library.getLicense(), e);
          }
        }

    private void notify( final License license,  final Exception e) {
          new EventHandler(EventRunner.getMainEventRunner()).postTask(new Runnable() {
            @Override
            public void run() {
            }
          });
        }
      });
    } else {
      GitHubLibrary.getOnListeners().onResultComplete(cache);
    }
  }

    private void openCache() {
    try {
      diskLruCache = DiskLruCache.open(
              Utils.getDiskCacheDir(context, "cache"),
              Utils.getAppVersion(context),
              1,
              1024 * 1024 * 10);
    } catch (IOException e) {
    }
  }
    private boolean saveCacheData(String key, String value) {
    if (diskLruCache.isClosed()) {
      openCache();
    }
    try {
      DiskLruCache.Editor editor = diskLruCache.edit(key);
      editor.newOutputStream(0).write(value.getBytes());
      editor.commit();
      return true;
    } catch (Exception e) {
      e.printStackTrace();
      return false;
    }
  }
    private String getCacheData(String key) {
    if (diskLruCache.isClosed()) {
      openCache();
    }
    try {
      String value = diskLruCache.get(key).getString(0);
      return value;
    } catch (Exception e) {
      return null;
    }
  }

  @Override
    public void onExpand(ExpandableLibrary library, boolean expanded) {
    int index = datas.indexOf(library);

    if (index == -1) {
      throw new IllegalStateException("Could not find library: " + library);
    }

    notifyDataSetItemRangeChanged(index * 2, 2);
  }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
      concomponent = component;
      switch (event.getAction()){
          case TouchEvent.PRIMARY_POINT_DOWN:
              ShapeElement shapeElement = new ShapeElement();
              shapeElement.setRgbColor(new RgbColor(220, 220, 220));
              concomponent.setBackground(shapeElement);
              break;
          case TouchEvent.PRIMARY_POINT_UP:
              ShapeElement shapeup = new ShapeElement();
              shapeup.setRgbColor(new RgbColor(255, 255, 255));
              concomponent.setBackground(shapeup);
              break;
          case TouchEvent.CANCEL:
              break;
      }
        return true;
    }

    private String getUrl(String address,Context context) {
        ohos.global.resource.ResourceManager resManager = context.getResourceManager();
        ohos.global.resource.RawFileEntry rawFileEntry = resManager.getRawFileEntry(address);
        StringBuffer stringBuffer = new StringBuffer();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(rawFileEntry.openRawFile()));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line);
            }
            return stringBuffer.toString();
        } catch (IOException e) {
            e.getMessage();
        }
        return "";
    }
}


